home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / SAT / HeartQuest sample ƒ / gameWindow.p < prev    next >
Encoding:
Text File  |  1993-10-04  |  20.3 KB  |  702 lines  |  [TEXT/PJMM]

  1. {================================================}
  2. {=============== Game window handler ================}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { This file holds the game window and game menu handlers for HeartQuest.}
  10. { This is where most game-specific code goes, except for the code describing}
  11. { each object. }
  12.  
  13. { GameWindInit is called to initialize, which initializes the window and installs}
  14. {handler procedures (note that menus are installed in main.p). It calls the routines}
  15. {to initialize offscreen GrafPorts and all the animated objects. }
  16.  
  17. { When the user selects New Game, StartGame is called to set up a new}
  18. { game, and then MoveIt, the game driver routine is called. }
  19.  
  20. unit GameWind;
  21.  
  22. interface
  23.  
  24.     uses
  25.         transskel, SAT,{Globals, Other, Emergency, OffScreen, Animator, SATSound}
  26.         GameGlobals, sPlayer, sFlypaper, sHeart, sBonus, sPoints, scores, SoundConst, Sound;
  27.  
  28.     procedure InitOffscreen;
  29.     procedure DoGameMenu (item: integer);
  30.     procedure GameWindInit;
  31.     procedure DoGameOver;
  32.  
  33.  
  34. implementation
  35.  
  36. {var}
  37. {mp: MonsterPtr; { Bra att ha en global tillgänglig. Dvs praktiskt... }
  38. {    SlemtorksHandlerPtr: ProcPtr;}
  39.  
  40.     procedure InitSprites;
  41.     begin
  42. { Set up the two offscreen GrafPorts "offScreen" and "backScreen". SAT has a standard}
  43. { way to do this. Let SAT draw the background PICT for us, too. }
  44. {SetupOffAndBack(132, 129);}
  45.  
  46. { Call the init routines for each the sprite unit! Don't forget this! }
  47.         initFlypaper;
  48.         initHeart;
  49.         initPlayer;
  50.         initBonus;
  51.         initPoints;
  52.     end;
  53.  
  54.     procedure DrawBackground;
  55.     forward;
  56.  
  57. { Setup a new level. This is called when the game starts ans at each new level.}
  58.     procedure SetupLevel (level: integer);
  59.         var
  60.             p: point;
  61.             i: integer;
  62.             mp, oldmp: SpritePtr;
  63.             r: rect;
  64.             s: Str255;
  65.             er: EventRecord; {For EventAvail}
  66.  
  67. { A routine to create a bunch of hearts }
  68.         procedure MakeHearts (howmany: integer);
  69.             var
  70.                 i: integer;
  71.                 mp: SpritePtr;
  72.         begin
  73.             for i := 1 to howmany do
  74.                 case rand(4) of
  75.                     0: 
  76.                         mp := NewSprite(-2, Rand(offSizeH - 112) + 17, 0, @HandleHeart, @SetupHeart, nil);
  77.                     1: 
  78.                         mp := NewSprite(-2, Rand(offSizeH - 112) + 17, offSizeV - 32, @HandleHeart, @SetupHeart, nil);
  79.                     2: 
  80.                         mp := NewSprite(-2, 0, Rand(offSizeV - 32) + 17, @HandleHeart, @SetupHeart, nil);
  81.                     3: 
  82.                         mp := NewSprite(-2, offSizeH - xsize, Rand(offSizeV - 32) + 17, @HandleHeart, @SetupHeart, nil);
  83.                 end;
  84.         end;
  85.  
  86.     begin { SetupLevel }
  87. {DrawBackground; Tar för lång tid?}
  88.  
  89. { Clear the sprite list }
  90.         mp := sRoot;
  91.         while mp <> nil do
  92.             begin
  93.                 oldmp := mp;
  94.                 mp := mp^.next;
  95.                 KillSprite(oldmp);
  96.             end;
  97. { Create all the sprites for the level, depending on the level number. }
  98.         case level of
  99.             1: 
  100.                 begin
  101.                     batchcount := 6;
  102.                     bonus := 250;
  103.                     MakeHearts(6);
  104.                     mp := NewSprite(-3, 10, 10, @HandleFlypaper, @SetupFlypaper, nil);
  105.                     mp := NewSprite(-3, offSizeH - xsize - 32, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  106.                 end;
  107.             2: 
  108.                 begin
  109.                     batchcount := 10;
  110.                     bonus := 300;
  111.                     MakeHearts(10);
  112.                     mp := NewSprite(-3, 10, 10, @HandleFlypaper, @SetupFlypaper, nil);
  113.                     mp := NewSprite(-3, offSizeH - xsize - 32, 20, @HandleFlypaper, @SetupFlypaper, nil);
  114.                     mp := NewSprite(-3, 20, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  115.                 end;
  116.             3: 
  117.                 begin
  118.                     batchcount := 12;
  119.                     MakeHearts(12);
  120.                     bonus := 350;
  121.                     mp := NewSprite(-3, 5, 5, @HandleFlypaper, @SetupFlypaper, nil);
  122.                     mp := NewSprite(-3, offSizeH - xsize - 32, 5, @HandleFlypaper, @SetupFlypaper, nil);
  123.                     mp := NewSprite(-3, 5, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  124.                     mp := NewSprite(-3, offSizeH - xsize - 32, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  125.                 end;
  126.             4: 
  127.                 begin
  128.                     batchcount := 12;
  129.                     MakeHearts(12);
  130.                     bonus := 350;
  131.                     mp := NewSprite(-3, 5, 5, @HandleFlypaper, @SetupFlypaper, nil);
  132.                     mp := NewSprite(-3, offSizeH - xsize - 32, 5, @HandleFlypaper, @SetupFlypaper, nil);
  133.                     mp := NewSprite(-3, 5, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  134.                     mp := NewSprite(-3, offSizeH - xsize - 32, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  135.                     mp := NewSprite(-3, 5, (offSizeV - 32) mod 2, @HandleFlypaper, @SetupFlypaper, nil);
  136.                     mp := NewSprite(-3, offSizeH - xsize - 32, (offSizeV - 32) mod 2, @HandleFlypaper, @SetupFlypaper, nil);
  137.                 end;
  138.             5: 
  139.                 begin
  140.                     batchcount := 10;
  141.                     MakeHearts(10);
  142.                     bonus := 380;
  143.                     mp := NewSprite(-3, 5, 5, @HandleFlypaper, @SetupFlypaper, nil);
  144.                     mp := NewSprite(-3, offSizeH - xsize - 32, 5, @HandleFlypaper, @SetupFlypaper, nil);
  145.                     mp := NewSprite(-3, 5, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  146.                     mp := NewSprite(-3, offSizeH - xsize - 32, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  147.                 end;
  148.             6: 
  149.                 begin
  150.                     batchcount := 12;
  151.                     MakeHearts(12);
  152.                     bonus := 420;
  153.                     mp := NewSprite(-3, 5, 5, @HandleFlypaper, @SetupFlypaper, nil);
  154.                     mp := NewSprite(-3, offSizeH - xsize - 32, 5, @HandleFlypaper, @SetupFlypaper, nil);
  155.                     mp := NewSprite(-3, 5, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  156.                     mp := NewSprite(-3, offSizeH - xsize - 32, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  157.                     mp := NewSprite(-3, offSizeH - xsize - 32, (offSizeV - 32) mod 2, @HandleFlypaper, @SetupFlypaper, nil);
  158.                 end;
  159.             otherwise
  160.                 begin
  161.                     batchcount := level * 2;
  162.                     MakeHearts(level * 2);
  163.                     bonus := 300 + 20 * level;
  164.                     for i := 0 to level - 1 do
  165.                         begin
  166.                             case rand(6) of
  167.                                 0: 
  168.                                     mp := NewSprite(-3, 5, 5, @HandleFlypaper, @SetupFlypaper, nil);
  169.                                 1: 
  170.                                     mp := NewSprite(-3, offSizeH - xsize - 32, 5, @HandleFlypaper, @SetupFlypaper, nil);
  171.                                 2: 
  172.                                     mp := NewSprite(-3, 5, 300, @HandleFlypaper, @SetupFlypaper, nil);
  173.                                 3: 
  174.                                     mp := NewSprite(-3, offSizeH - xsize - 32, offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  175.                                 4: 
  176.                                     mp := NewSprite(-3, (offSizeH - xsize - 32) div 2, 5, @HandleFlypaper, @SetupFlypaper, nil);
  177.                                 5: 
  178.                                     mp := NewSprite(-3, (offSizeH - xsize - 32), offSizeV - 32, @HandleFlypaper, @SetupFlypaper, nil);
  179.                             end; { case }
  180.                         end;
  181.                 end;
  182.         end;
  183. { Reposition mouse to the center of the game area. }
  184.         p.h := 256;
  185.         p.v := 171;
  186.         SetMouse(p);
  187. { Make the player sprite. }
  188.         mp := NewSprite(2, (offSizeH - xsize) div 2, offSizeV div 2, @HandlePlayer, @SetupPlayer, @HitPlayer);
  189. { Copy backScreen to offScreen to erase old sprites. }
  190.         CopyBits(backScreen^.portBits, offScreen^.portBits, offScreen^.portRect, offScreen^.portRect, srcCopy, nil);
  191.         PeekOffScreen; {replaces the following out-commented lines:}
  192. {SetPort(gameWind);}
  193. {CopyBits(offScreen^.portBits, gameWind^.portBits, offScreen^.portRect, offScreen^.portRect, srcCopy, nil);}
  194.  
  195.         AddScore(0);
  196. { Do one frame of animation just to draw all the objects. }
  197.         RunSAT(false); {false or features^^.PlotFast; slow is ok - no hurry!}
  198.  
  199. { Draw a message and wait for click- this is a bit ugly. Consider other ways. }
  200.         SetPort(gameWind);
  201.         SetRect(r, offSizeH div 2 - 110 + 2, offSizeV div 2 + 35 + 2, offSizeH div 2 + 110 + 2, offSizeV div 2 + 60 + 2); {offset by 2 pixels}
  202.         PaintRect(r);
  203.         SetRect(r, offSizeH div 2 - 110, offSizeV div 2 + 35, offSizeH div 2 + 110, offSizeV div 2 + 60);
  204.         EraseRect(r);
  205.  
  206.         MoveTo(offSizeH div 2 - 105, offSizeV div 2 + 50);
  207.         if level = 1 then
  208.             drawstring('Click the mouse to start the game.')
  209.         else
  210.             begin
  211.                 DrawString('Click the mouse to start level ');
  212.                 NumToString(level, s);
  213.                 DrawString(s);
  214.                 DrawChar('.');
  215.             end;
  216.  
  217.         if false then
  218.             while not button do
  219.                 ;
  220.  
  221. {Wait until something happens}
  222.         FlushEvents(EveryEvent, 0); { To forget events, like mouse clicks etc. }
  223.         repeat
  224.         until EventAvail(mDownMask + keyDownMask, er);
  225.  
  226.  
  227. { Redraw to get rid of the message we just made. }
  228.         PeekOffScreen;
  229. {SetPort(gameWind);}
  230. {CopyBits(offScreen^.portBits, gameWind^.portBits, offScreen^.portRect, offScreen^.portRect, srcCopy, nil);}
  231.     end; { SetupLevel }
  232.  
  233. { Start a new game. Initialize level, score, number of lives, and call setuplevel to make the first level. }
  234.     procedure StartGame;
  235.     begin
  236.         ZeroScore;
  237.         Level := 1;
  238.  
  239.         setuplevel(level);
  240.     end;
  241.  
  242. { Game Over procedure. Draw "Game Over" text, check high scores. }
  243.  
  244.     procedure DoGameOver;
  245.         var
  246. { Variables for the Game Over-box }
  247.             theRect, theRect2: rect;
  248.             thePict: Handle;
  249.             bredd, i: integer;
  250.             dx, dy: integer;
  251.             time: longint;
  252.     begin
  253.         SetItem(GameMenu, Pause, 'Pause');
  254. { Game Over display! }
  255.         SetPort(gameWind);
  256.         if ColorFlag and (OurDepth <> 1) then
  257.             thePICT := GetResource('PICT', 129)
  258.         else
  259.             thePICT := GetResource('PICT', 128);
  260.         TheRect := PicHandle(thePICT)^^.picFrame;
  261.         TheRect.right := TheRect.right - TheRect.left;
  262.         TheRect.bottom := TheRect.bottom - TheRect.top;
  263.         TheRect.top := 0;
  264.         TheRect.left := 0;
  265.  
  266.         dx := (offSizeH - (TheRect.right - TheRect.left)) div 2 - TheRect.left;
  267.         dy := (offSizeV - (TheRect.bottom - TheRect.top)) div 2 - TheRect.top;
  268.  
  269. {offsetrect(TheRect, 130, 100);}
  270.         offsetrect(TheRect, dx, dy);
  271.  
  272.         bredd := TheRect.right - TheRect.left;
  273.         TheRect2 := TheRect;
  274.  
  275.         i := 1;
  276.         repeat
  277.             time := TickCount;
  278.             TheRect.right := TheRect2.right - bredd * (80 - i) div 160;
  279.             TheRect.left := TheRect2.left + bredd * (80 - i) div 160;
  280.             DrawPicture(PicHandle(thePICT), TheRect);
  281.             i := i + TickCount - time;
  282.         until i >= 80;
  283.  
  284.         SetPort(offScreen);
  285.         DrawPicture(PicHandle(thePICT), TheRect);
  286.         SetPort(gameWind);
  287.  
  288.         invalrect(Therect);
  289.  
  290.         SATSoundShutUp; { Dispose of sound channel }
  291.  
  292.         FlushEvents(EveryEvent, 0); { To forget events, like mouse clicks etc. }
  293.         ShowCursor;
  294.  
  295.         updatehigh; { Game over, was it high score? }
  296.     end;
  297.  
  298.  
  299. { This routine is the game driver. It calls the "Animator" package until the game ends or is paused. }
  300. { I also read the keyboard here. This could optionally be moved to the "player object" module. }
  301.  
  302.     procedure MoveIt;
  303.         var
  304.             fr, tr, r: Rect;
  305.             pt: Point;
  306.             h: Integer;
  307.             truepos: Longint;
  308. {n, x: Integer;    { Are these used? }
  309.             t, l: longint;
  310.             truepos32, bredd32: integer; { Some old bugfix that I no longer remember... }
  311.             truepos19, bredd19: integer;
  312.             theEvent: EventRecord; { för att testa musklick }
  313. { To check for key clicks with GetKeys:  - no longer used. km: KeyMap;}
  314.             hasEvent: Boolean;
  315.             ignore: OSerr;
  316.     begin
  317.         stillrunning := true; { A flag that tells whether or not to quit this routine. }
  318.  
  319.         HideCursor; { NOTE: No matter how we leave the MoveIt procedure, we should ShowCursor. }
  320.  
  321.         pt.h := 256;
  322.         pt.v := 171;
  323.         SetMouse(pt);
  324.  
  325. { Main loop! Keep running until the game is paused or ends. }
  326.         while stillrunning = true do
  327.             begin
  328.                 t := TickCount;
  329.                 SetPort(gameWind);
  330.                 SetPort(offScreen);
  331.  
  332. { Here is the real heart of the loop: call Animator once per loop. It will call all the objects. }
  333.                 RunSAT(features^^.plotFast);
  334. {SATSoundEvents; No longer needed - included in RunSAT!}
  335.  
  336. { All the rest of the main loop is game specific, next level, bonus handling, etc. }
  337.                 if (batchcount < 1) then
  338.                     begin
  339.                         SATSoundShutUp;
  340.                         if false then
  341.                             if features^^.sound then
  342.                                 ignore := SndPlay(nil, GetResource('snd ', SadarSnd), false);
  343.  
  344.                         SATSoundPlay(SadarSndH, 0, true);
  345.                         repeat
  346.                             SATSoundEvents
  347.                         until SATSoundDone;
  348.  
  349.                         if bonus > 0 then
  350.                             while bonus > 0 do
  351.                                 begin
  352.                                     Bonus := Bonus - 10;
  353. { SndPlay would have been ok here, since we want to play this synchronously.}
  354.  
  355.                                     SATSoundPlay(KlounkSndH, 0, true);
  356.                                     repeat
  357.                                         SATSoundEvents
  358.                                     until SATSoundDone;
  359.  
  360.                                     if false then
  361.                                         if features^^.sound then
  362.                                             ignore := SndPlay(nil, GetResource('snd ', KlounkSnd), false);
  363.  
  364.                                     if bonus < 0 then
  365.                                         begin
  366.                                             l := bonus;
  367.                                             bonus := 0;
  368.                                             AddScoreS(10 + l); {A special synchronous version of AddScore}
  369.                                         end
  370.                                     else
  371.                                         AddScoreS(10); { Bonus! }
  372.                                 end { if bonus > 0 }
  373.                         else if features^^.macho then
  374.                             stillrunning := false; { If no bonus, game over }
  375.  
  376.                         if (stillrunning and features^^.macho) or (level < 3) then {level < 4}
  377.                             begin
  378.                                 level := level + 1;
  379.                                 SetupLevel(level);
  380.                                 AddScoreS(0); {To update the level number}
  381.                             end
  382.                         else
  383.                             stillrunning := false;
  384.                     end; {if (batchcount < 1)}
  385.  
  386. { Check for keys being pressed }
  387.                 if features^^.allowBG then { if we are allowed to use the normal method }
  388.                     begin
  389.                         SystemTask;
  390. { Replaced the following call by WaitNextEvent if you want to be modern (but less backwards compatible). :-) }
  391.                         hasEvent := GetNextEvent(keyDownMask, theEvent)
  392.                     end
  393.                 else {Otherwise, use the faster GetOSEvent}
  394.                     begin
  395.                         hasEvent := GetOSEvent(keyDownMask, theEvent)
  396.                     end;
  397.  
  398. {If there was a keydown, see if it was one of the menu options that we support when running.}
  399.                 if hasEvent then { there was a keydown }
  400.                     if BitAnd(theEvent.modifiers, cmdKey) <> 0 then
  401.                         begin
  402.                             case char(BitAnd(theEvent.message, charCodeMask)) of
  403.                                 'p': 
  404.                                     begin
  405.                                         PauseFlag := true;
  406.                                         SATSoundShutUp; { Dispose of sound channel }
  407.                                         ShowCursor;
  408.                                         flushevents(6 + 8, 0); { In order to forget the cmd-p }
  409.                                         SetItem(GameMenu, Pause, 'Resume');
  410.                                         exit(MoveIt);
  411.                                     end;
  412.                                 '.': 
  413.                                     StillRunning := false;
  414.                                 'q': 
  415.                                     begin
  416.                                         StillRunning := false;
  417.                                         SkelWhoa;
  418.                                     end;
  419.                                 's': 
  420.                                     begin
  421.                                         DoGameMenu(sound);
  422.                                     end;
  423.                                 otherwise
  424.                                     ;
  425.                             end; {case}
  426.                         end;
  427.  
  428. { Delay, using TickCount so it doesn't matter how fast our Mac is. }
  429.                 while ((TickCount - t) < 3) do
  430.                     ;
  431.  
  432.             end; { while stillrunning (main loop) }
  433.  
  434.         DoGameOver;
  435.     end;
  436.  
  437.  
  438. {We draw the background ourselves rather than using a simple backdrop PICT, to save space and to get the}
  439. {dithered background.}
  440.     procedure DrawBackground;
  441.         var
  442.             ph: PicHandle;
  443.             ignore: OSErr;
  444.             ramp: CTabHandle;
  445.             extraOff: CGrafPtr;
  446.             extraOffGD: GDHandle;
  447.             col: RGBColor;
  448.             thinr, r: Rect;
  449.             i, j: integer;
  450.  
  451.             posH, posV, scale, height, width: longint; {For scaling the trees}
  452.     begin
  453.         SATSetPortBackScreen;
  454.         SetRect(r, 0, 0, offSizeH, offSizeV);
  455.         if ColorFlag then
  456.             begin
  457. {Draw our PICT under it.}
  458.                 if OurDepth = 1 then
  459.                     ph := GetPicture(133)
  460.                 else
  461.                     ph := GetPicture(132); {color PICT}
  462.                 if ph = nil then
  463.                     ReportStr('Can''t get PICT.');
  464.                 if ph <> nil then
  465.                     begin
  466.                         DrawPicture(ph, r);
  467.                         ReleaseResource(handle(ph));
  468.                     end;
  469. {Set up an 8 bit offscreen with a special color table, and ditherCopy to backScreen.}
  470.                 ramp := GetCTable(128);
  471.                 if ramp = nil then
  472.                     ReportStr('Can''t get CLUT 128.');
  473.                 if ramp <> nil then
  474.                     begin
  475.                         SetRect(thinr, 0, 0, 5, offSizeV);
  476.                         ignore := CreateOffScreen(thinr, 8, ramp, extraOff, extraOffGD);
  477.                         if ignore <> noErr then
  478.                             ReportStr('Can''t make offscreen.');
  479.                         SetPort(GrafPtr(extraOff));
  480.                         SetGDevice(extraOffGD);
  481.                         PaintRect(extraOff^.portRect);
  482. {Make a scale of shades}
  483.                         for i := 0 to offSizeV do
  484.                             begin
  485. {$PUSH}
  486. {$V-}
  487.                                 col.green := BSL(i, 16) div offSizeV;
  488. {$POP}
  489.                                 col.red := col.green;
  490.                                 col.blue := col.green;
  491.                                 RGBForeColor(col);
  492.                                 MoveTo(0, i);
  493.                                 LineTo(5, i); {offSizeH}
  494.                             end;
  495.  
  496.                         col.red := 0;
  497.                         col.green := 0;
  498.                         col.blue := 0;
  499.                         RGBForeColor(col);
  500.  
  501.                         r.top := offSizeV div 4;
  502.                         thinr.top := offSizeV div 4;
  503.  
  504.                         SATSetPortBackScreen;
  505.                         CopyBits(GrafPtr(extraOff)^.portBits, backScreen^.portBits, thinr, r, srcCopy + ditherCopy, nil);
  506.                         DisposeOffscreen(extraOff, extraOffGD);
  507.  
  508.                     end;
  509.  
  510.             end
  511.         else
  512.             begin {This could just as well have been done by SAT}
  513.                 ph := GetPicture(133); {bw PICT}
  514.                 SATSetPortBackScreen;
  515.                 if ph <> nil then
  516.                     begin
  517.                         DrawPicture(ph, r);
  518.                         ReleaseResource(handle(ph));
  519.                     end;
  520.             end;
  521.  
  522. {Draw trees using PICTs!}
  523.  
  524. {First get the right PICT}
  525.         if OurDepth = 1 then
  526.             begin
  527.                 ph := GetPicture(135); {bw tree PICT}
  528.             end
  529.         else
  530.             begin
  531.                 ph := GetPicture(134); {color tree PICT}
  532.             end;
  533.  
  534. {Scale by ph^^.picframe}
  535.         for i := 0 to 10 do
  536. {For more trees: for j := i to 4 do}
  537.             begin
  538.                 posH := Rand(offSizeH);
  539.                 posV := offSizeV div 2 + longint(i) * i * offSizeV div 300;
  540.  
  541.                 scale := (posV - offSizeV div 4) div 17;
  542.                 height := scale * (ph^^.picframe.bottom - ph^^.picframe.top) div 40;
  543.                 width := scale * (ph^^.picframe.right - ph^^.picframe.left) div 40;
  544.  
  545.                 r.top := posV - height;
  546.                 r.bottom := posV;
  547.                 r.right := posH + width;
  548.                 r.left := posH;
  549.  
  550.                 DrawPicture(ph, r);
  551.             end;
  552.  
  553.         ReleaseResource(handle(ph));
  554.  
  555.         CopyBits(backScreen^.portBits, offScreen^.portBits, backScreen^.portRect, backScreen^.PortRect, srcCopy + ditherCopy, nil);
  556.         SATSetPortScreen;
  557.     end;
  558.  
  559.  
  560.     procedure GameWindUpdate;
  561.         var
  562.             s: str255;
  563.             r: Rect;
  564.             crsr: CursHandle;
  565.     begin
  566. {When the depth has changed, the game wind will get an update event,}
  567. {so let's give SAT a chance to update itself before updating!}
  568.  
  569.         crsr := GetCursor(WatchCursor);
  570.         SetCursor(crsr^^);
  571.         if SATDepthChangeTest then
  572.             begin
  573.                 DrawBackground;
  574.             end;
  575.         ReleaseResource(handle(crsr));
  576.         InitCursor;
  577.  
  578.         PeekOffScreen;
  579.         AddScore(0);
  580.     end;
  581.  
  582.     procedure DoGameMenu (item: integer);
  583.     begin
  584.         case (item) of
  585.             run: 
  586.                 begin
  587. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  588.                     if SATDepthChangeTest then {Update if necessary}
  589.                         DrawBackground;
  590.                     if not ((OurDepth = 1) or (OurDepth = 4) or (OurDepth = 8)) and features^^.PlotFast then
  591.                         begin
  592.                             reportstr('Please uncheck ''Fast animation'' or set the monitor to 1-, 4- or 8-bit mode in the Control Panel.');
  593.                             exit(DoGameMenu);
  594.                         end;
  595.                     if pauseFlag then
  596.                         if QuestionStr('End the Current game?') then
  597.                             DoGameMenu(abort)
  598.                         else
  599.                             exit(DoGameMenu);
  600.                     DisableItem(gameMenu, macho);
  601.                     ShowWindow(gameWind);
  602.                     SelectWindow(gameWind);
  603.                     StartGame;
  604.                     GameWindUpdate;
  605.                     MoveIt;
  606.                     if not pauseFlag then
  607.                         EnableItem(GameMenu, macho);
  608.                 end;
  609.             sound: 
  610.                 begin
  611.                     features^^.sound := not features^^.sound;
  612.                     CheckItem(GameMenu, sound, features^^.sound);
  613.                     if features^^.sound then { Tell the sound package our settings, so we don't have to bother. }
  614.                         SATSoundOn
  615.                     else
  616.                         SATSoundOff;
  617.                     ChangedResource(handle(features));
  618.                 end;
  619.             macho: 
  620.                 begin
  621.                     features^^.macho := not features^^.macho;
  622.                     CheckItem(GameMenu, macho, features^^.macho);
  623.                     ChangedResource(handle(features));
  624.                 end;
  625.             AllowBG: 
  626.                 begin
  627.                     features^^.AllowBG := not features^^.AllowBG;
  628.                     CheckItem(GameMenu, AllowBG, features^^.AllowBG);
  629.                     ChangedResource(handle(features));
  630.                 end;
  631.             FastAnimation: 
  632.                 begin
  633.                     features^^.PlotFast := not features^^.PlotFast;
  634.                     CheckItem(GameMenu, FastAnimation, features^^.PlotFast);
  635.                     ChangedResource(handle(features));
  636.                 end;
  637.             pause: 
  638.                 begin
  639. { Pause is only interesting here as "resume". }
  640.                     if pauseFlag then
  641.                         begin
  642. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  643.                             if SATDepthChangeTest then {Update if necessary}
  644.                                 DrawBackground;
  645.                             if not ((OurDepth = 1) or (OurDepth = 4) or (OurDepth = 8)) and features^^.PlotFast then
  646.                                 begin
  647.                                     reportstr('Please uncheck ''Fast animation'' or set the monitor to 1-, 4- or 8-bit mode in the Control Panel.');
  648.                                     exit(DoGameMenu);
  649.                                 end;
  650.                             SetItem(GameMenu, pause, 'Pause');
  651.                             pauseFlag := false;
  652.                             ShowWindow(gameWind);
  653.                             SelectWindow(gameWind);
  654.                             GameWindUpdate;
  655.                             MoveIt;
  656.                             if not pauseFlag then
  657.                                 EnableItem(GameMenu, macho);
  658.                         end;
  659.                 end;
  660.             abort: 
  661.                 begin
  662.                     if pauseFlag then
  663.                         begin
  664.                             SetItem(GameMenu, Pause, 'Pause');
  665.                             DoGameOver;
  666.                             pauseFlag := false;
  667.                             EnableItem(GameMenu, macho);
  668.                         end
  669.                 end;
  670.         end;
  671.     end;
  672.  
  673.     procedure GameWindMouse (thePoint: Point; theTime: longint; theMods: integer; myProc: ProcPtr);
  674.     begin
  675.     end;
  676.  
  677.     procedure GameWindIdle;
  678.     begin
  679.     end;
  680.  
  681.     procedure GameWindClose;
  682.     begin
  683.     end;
  684.  
  685.     procedure GameWindInit;
  686.     begin
  687. { Tell TransSkel to handle all the tedious things with GameWind. }
  688.         dummy := SkelWindow(GameWind, @GameWindMouse, nil, @GameWindUpdate, nil, @GameWindClose, nil, @GameWindIdle, false);
  689.  
  690. { Initialize the sprites }
  691.         InitSprites;
  692.  
  693. {We draw the background ourselves in this game.}
  694.         DrawBackground;
  695.  
  696. { Draw the contents of the window (to give the user something to look at during the rest of startup). }
  697.         ShowWindow(gameWind);
  698.         SelectWindow(gameWind);
  699.         PeekOffScreen;
  700.     end;
  701.  
  702. end.